Skip to content

fix(validate): catch typos in containers config and close self-scan UX gaps#118

Merged
eFAILution merged 2 commits intofeat/argus-portabilityfrom
fix/argus-validate-containers-and-followups
May 6, 2026
Merged

fix(validate): catch typos in containers config and close self-scan UX gaps#118
eFAILution merged 2 commits intofeat/argus-portabilityfrom
fix/argus-validate-containers-and-followups

Conversation

@eFAILution
Copy link
Copy Markdown
Collaborator

Description

Three fixes plus a workflow refactor, all surfaced while running argus scan and argus scan container against argus's own source and image set during the validation pass after PR #117.

Changes Made

  • Added new scanner/workflow
  • Modified existing scanner/workflow
  • Updated documentation
  • Fixed bug
  • Other (please specify)

Details

1. argus validate now validates the top-level containers: block

Until now argus/core/schema.py recognized containers as a known top-level key but never inspected its contents. Typos and structural mistakes only surfaced (or failed silently) at scan time:

Mistake Old behavior New behavior
image_path: instead of dockerfile: Silent — image entry treated as missing both fields Warning surfaced by argus validate
Empty images: [] Engine no-op Warning surfaced
Image entry with neither image: nor dockerfile: Silent Error surfaced
Sub-scanner outside {trivy, grype, syft} Engine error mid-scan Error surfaced upfront
containers: not-a-mapping Deep traceback Already-actionable error (now also at validate time)

New _validate_containers helper walks the block and produces the same ConfigError objects the rest of the validator already emits, so both argus validate and the pre-scan validation in ArgusConfig._load_file pick it up. 15 unit tests in argus/tests/core/test_schema_containers.py.

2. argus scan container auto-loads argus.yml when no --config is given

The source-scan dispatcher has always done this; the container subcommand used to require an explicit --config FILE even when argus.yml sat right at the project root with a populated containers: block. Now both flows search the canonical _DEFAULT_CONFIG_NAMES list (argus.yml, argus.yaml, .argus.yml, .argus.yaml). CLI flags still take precedence over config-file values.

3. .ai/ doc cleanup

The recent context refresh (commit fa22779) claimed argus list and argus version are subcommands. They're not — argus --version is a top-level flag, and the registered subcommand list is init / scan / classify / collect / report / validate / mcp / completion / cache / view. .ai/context.yaml and .ai/architecture.yaml corrected.

4. .github/workflows/build-containers.yml — argus.yml as matrix source of truth

Hardcoded matrices in three places (build, scan, test-cli) replaced with a single preflight matrix job that reads argus.yml's containers.images list and emits a JSON matrix the downstream jobs consume via fromJson(needs.matrix.outputs.matrix). Adding a fifth scanner image is now one entry in argus.yml, not three matrix edits across the workflow plus the dogfood config.

The actual scanning still runs aquasecurity/trivy-action + anchore/scan-action — authored actions, not argus-scanning-argus. Argus-scanning-argus to validate argus is circular trust, and the user explicitly called this out:

Scanning argus with argus to prove that argus is secure may be bad taste.

So argus.yml drives the matrix, the trust boundary stays outside our own codebase.

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • Tested with different scanner combinations

Test Results

  • New schema tests: 15 unit tests in test_schema_containers.py (happy paths, structural errors, image-entry validation, sub-scanner whitelist, unknown-key warnings)
  • New CLI test: 1 regression test for the auto-config-load behavior
  • Full SDK suite: 1513 passed, 8 skipped (was 1497 on main; +16 from new tests, no regressions)
  • Pre-commit hooks: all green (yamllint, codespell, hardcoded-secrets, etc.)

Manual validation against the local checkout (the trigger for this PR):

  • argus scan --config argus.yml: 6 scanners, 163 findings
  • argus scan container --config argus.yml: 4 images built locally, 230s wall, 141 total findings (98 unique)
  • argus scan container (no --config): now auto-detects argus.yml, runs identically to the explicit form ✅

Security Considerations

  • No security impact
  • Security enhancement
  • Potential security implications (explain below)

Security Details

The workflow refactor (#4) makes argus.yml the input to a CI-time matrix builder, but the runner step reads only the checked-out repo file via yq (no untrusted input from PR titles/body/etc.). The pre-commit yamllint and the husky hook chain reviewed the change.

The trust-boundary point is the substantive one: by keeping aquasecurity/trivy-action and anchore/scan-action for the actual container scanning, argus's own image set is validated by external tools rather than by argus itself.

AI Context Updates (.ai/)

  • .ai/architecture.yaml updated (removed false argus list claim, added missing --version clarification)
  • .ai/workflows.yaml updated (if commands/tasks changed)
  • .ai/decisions.yaml updated (if design decision made)
  • .ai/errors.yaml updated (if common error addressed)
  • N/A - No .ai/ updates needed

.ai/context.yaml cli_subcommands list reorganized; argus list and argus version removed (they don't exist); --version flag explicitly noted under a new cli_flags: section.

Checklist

  • Code follows project style guidelines
  • Documentation updated (.ai/ context corrections, workflow comments)
  • Changelog updated (if applicable)
  • All tests pass
  • Reviewed by at least one maintainer
  • Reviewed CONTRIBUTING.md guidelines

For New Scanners/Actions (if applicable)

  • N/A — no new scanners/actions

Follow-ups (not in this PR)

Surfaced during the same dogfooding pass; deferred to keep this PR focused:

  • lint-dockerfile doesn't appear in source-scan results even when its container image (hadolint) is unavailable locally. Other scanners surface as failed-execution rows with metadata.execution_failed; lint-dockerfile silently drops out. Worth investigating — likely a registry routing issue between LINTER_REGISTRY and SCANNER_REGISTRY for the engine's failure-row construction.

Three fixes plus a workflow refactor, all surfaced while running argus
against argus's own source and container images.

1. argus validate now validates the top-level containers block. Until
   now the schema validator recognized 'containers' as a known top-level
   key but never inspected its contents — typos (e.g. image_path
   instead of dockerfile), an empty images list, missing both image and
   dockerfile on an entry, and sub-scanner names outside trivy/grype/
   syft all sailed past argus validate and only surfaced (or failed
   silently) at scan time. New _validate_containers helper in
   argus/core/schema.py walks the block and produces the same
   ConfigError objects the rest of the validator already emits, so
   argus validate and the pre-scan validation in
   ArgusConfig._load_file both pick it up. 15 unit tests in
   argus/tests/core/test_schema_containers.py.

2. argus scan container auto-loads argus.yml when no --config is
   given. The source-scan dispatcher has always done this; the
   container subcommand used to require an explicit --config FILE
   even when an argus.yml sat right at the project root with a
   containers block. Now both flows search the canonical
   _DEFAULT_CONFIG_NAMES list. CLI flags still take precedence over
   config-file values. Test in argus/tests/test_cli.py.

3. .ai/ doc cleanup: the recent context refresh claimed argus list
   and argus version are subcommands. They are not — argus --version
   is a top-level flag, and the registered subcommand list is now
   correctly spelled out in .ai/context.yaml and
   .ai/architecture.yaml.

4. .github/workflows/build-containers.yml: extract the four
   hard-coded image entries into a preflight matrix job that reads
   argus.yml containers.images and emits a JSON matrix the build,
   scan, and test-cli jobs consume. argus.yml becomes the single
   source of truth for the dogfood image list — adding a fifth
   scanner image is now one entry, not three matrix edits across the
   workflow plus the dogfood config. The actual scanning still runs
   aquasecurity/trivy-action and anchore/scan-action (authored
   actions, not argus-scanning-argus) — argus.yml drives the matrix,
   the trust boundary stays outside our own codebase.

Tests: 1513 passed (was 1497 before this PR; 16 new from schema tests
and the auto-config-load regression test).
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

E2E Test Coverage Report

Action E2E Test Status Notes
ai-summary ⚪ Exception Manual-only action - triggered via dedicated ai-summary.yml workflow with user-supplied PR number
comment-pr ⚪ Exception Utility action - tested indirectly by all scanner and linter actions
get-job-id ⚪ Exception Utility action - tested indirectly by other jobs
linter-dockerfile ✅ Tested
linter-javascript ✅ Tested
linter-json ✅ Tested
linter-python ✅ Tested
linter-terraform ✅ Tested
linter-yaml ✅ Tested
linting-summary ✅ Tested
parse-container-config ✅ Tested
parse-zap-config ✅ Tested
scanner-bandit ✅ Tested
scanner-checkov ✅ Tested
scanner-clamav ✅ Tested
scanner-codeql ✅ Tested
scanner-container ✅ Tested
scanner-container-summary ⚪ Exception Tested as part of scanner-container
scanner-dependency-review ✅ Tested
scanner-gitleaks ✅ Tested
scanner-opengrep ✅ Tested
scanner-osv ✅ Tested
scanner-supply-chain ✅ Tested
scanner-syft ✅ Tested
scanner-trivy-iac ✅ Tested
scanner-zap ✅ Tested
scanner-zap-summary ⚪ Exception Tested as part of scanner-zap
scn-detector ✅ Tested
security-summary ⚪ Exception Tested in test-summary job

Summary

  • Total Actions: 29
  • Covered: 29
  • Missing E2E Tests: 0
  • Coverage: 100%

✅ All Actions Have E2E Coverage

@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 98.90710% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
argus/cli.py 96.00% 1 Missing ⚠️
argus/core/schema.py 98.03% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

🔒 Argus Container Security Scan

Branch: fix/argus-validate-containers-and-followups
Commit: 1923695

📊 Combined Findings Summary

🚨 Critical ⚠️ High 🟡 Medium 🔵 Low 📦 Total 🔢 Unique
1 22 65 64 152 152

Scanned: 4 containers | Build Failures: 0

📦 Container Breakdown

Container Image 🚨 Crit ⚠️ High 🟡 Med 🔵 Low Total Unique Status
cli ghcr.io/huntridge-labs/argus/cli:19236951317d0f7b30fd807408558548f0b20cbb 1 11 16 1 29 29
scanner-bandit ghcr.io/huntridge-labs/argus/scanner-bandit:19236951317d0f7b30fd807408558548f0b20cbb 0 0 2 0 2 2
scanner-opengrep ghcr.io/huntridge-labs/argus/scanner-opengrep:19236951317d0f7b30fd807408558548f0b20cbb 0 7 42 63 112 112
scanner-supply-chain ghcr.io/huntridge-labs/argus/scanner-supply-chain:19236951317d0f7b30fd807408558548f0b20cbb 0 4 5 0 9 9

🔍 Detailed Findings by Container

🚨 cli - 29 vulnerabilities (23 unique)

Image: ghcr.io/huntridge-labs/argus/cli:19236951317d0f7b30fd807408558548f0b20cbb

Combined (Deduplicated)

🚨 Critical ⚠️ High 🟡 Medium 🔵 Low Total Unique
1 11 16 1 29 23
🔷 Trivy Scanner (29 findings, 23 unique)
CVE Severity Package Version Fixed
CVE-2025-68121 🚨 CRITICAL stdlib v1.24.11 1.24.13, 1.25.7, 1.26.0-rc.3
CVE-2026-32280 ⚠️ HIGH stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-32281 ⚠️ HIGH stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-32283 ⚠️ HIGH stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-33810 ⚠️ HIGH stdlib v1.26.1 1.26.2
CVE-2025-61726 ⚠️ HIGH stdlib v1.24.11 1.24.12, 1.25.6
CVE-2025-61728 ⚠️ HIGH stdlib v1.24.11 1.24.12, 1.25.6
CVE-2026-25679 ⚠️ HIGH stdlib v1.24.11 1.25.8, 1.26.1
CVE-2026-32280 ⚠️ HIGH stdlib v1.24.11 1.25.9, 1.26.2
CVE-2026-32281 ⚠️ HIGH stdlib v1.24.11 1.25.9, 1.26.2
CVE-2026-32283 ⚠️ HIGH stdlib v1.24.11 1.25.9, 1.26.2
CVE-2026-34040 ⚠️ HIGH github.com/docker/docker v28.5.2+incompatible 29.3.1
CVE-2026-3219 🟡 MEDIUM pip 26.0.1 N/A
CVE-2026-6357 🟡 MEDIUM pip 26.0.1 26.1
CVE-2026-32282 🟡 MEDIUM stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-32288 🟡 MEDIUM stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-32289 🟡 MEDIUM stdlib v1.26.1 1.25.9, 1.26.2
CVE-2025-11579 🟡 MEDIUM github.com/nwaples/rardecode/v2 v2.1.0 2.2.0
CVE-2025-58058 🟡 MEDIUM github.com/ulikunitz/xz v0.5.12 0.5.15
CVE-2025-47914 🟡 MEDIUM golang.org/x/crypto v0.35.0 0.45.0
CVE-2025-58181 🟡 MEDIUM golang.org/x/crypto v0.35.0 0.45.0
CVE-2025-61730 🟡 MEDIUM stdlib v1.24.11 1.24.12, 1.25.6
CVE-2026-27142 🟡 MEDIUM stdlib v1.24.11 1.25.8, 1.26.1
CVE-2026-32282 🟡 MEDIUM stdlib v1.24.11 1.25.9, 1.26.2
CVE-2026-32288 🟡 MEDIUM stdlib v1.24.11 1.25.9, 1.26.2
CVE-2026-32289 🟡 MEDIUM stdlib v1.24.11 1.25.9, 1.26.2
CVE-2026-33997 🟡 MEDIUM github.com/docker/docker v28.5.2+incompatible 29.3.1
CVE-2026-41506 🟡 MEDIUM github.com/go-git/go-git/v5 v5.17.2 5.18.0
CVE-2026-27139 🔵 LOW stdlib v1.24.11 1.25.8, 1.26.1
⚓ Grype Scanner (0 findings, 0 unique)

✅ No vulnerabilities detected by Grype

🟡 scanner-bandit - 2 vulnerabilities (2 unique)

Image: ghcr.io/huntridge-labs/argus/scanner-bandit:19236951317d0f7b30fd807408558548f0b20cbb

Combined (Deduplicated)

🚨 Critical ⚠️ High 🟡 Medium 🔵 Low Total Unique
0 0 2 0 2 2
🔷 Trivy Scanner (2 findings, 2 unique)
CVE Severity Package Version Fixed
CVE-2026-3219 🟡 MEDIUM pip 26.0.1 N/A
CVE-2026-6357 🟡 MEDIUM pip 26.0.1 26.1
⚓ Grype Scanner (0 findings, 0 unique)

✅ No vulnerabilities detected by Grype

⚠️ scanner-opengrep - 114 vulnerabilities (50 unique)

Image: ghcr.io/huntridge-labs/argus/scanner-opengrep:19236951317d0f7b30fd807408558548f0b20cbb

Combined (Deduplicated)

🚨 Critical ⚠️ High 🟡 Medium 🔵 Low Total Unique
0 7 42 63 114 50
🔷 Trivy Scanner (114 findings, 49 unique)
CVE Severity Package Version Fixed
CVE-2026-4878 ⚠️ HIGH libcap2 1:2.75-10+b8 N/A
CVE-2025-69720 ⚠️ HIGH libncursesw6 6.5+20250216-2 N/A
CVE-2026-29111 ⚠️ HIGH libsystemd0 257.9-1~deb13u1 N/A
CVE-2025-69720 ⚠️ HIGH libtinfo6 6.5+20250216-2 N/A
CVE-2026-29111 ⚠️ HIGH libudev1 257.9-1~deb13u1 N/A
CVE-2025-69720 ⚠️ HIGH ncurses-base 6.5+20250216-2 N/A
CVE-2025-69720 ⚠️ HIGH ncurses-bin 6.5+20250216-2 N/A
CVE-2026-27456 🟡 MEDIUM bsdutils 1:2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM bsdutils 1:2.41-5 N/A
CVE-2026-27456 🟡 MEDIUM libblkid1 2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM libblkid1 2.41-5 N/A
CVE-2026-4046 🟡 MEDIUM libc-bin 2.41-12+deb13u2 N/A
CVE-2026-4437 🟡 MEDIUM libc-bin 2.41-12+deb13u2 N/A
CVE-2026-4438 🟡 MEDIUM libc-bin 2.41-12+deb13u2 N/A
CVE-2026-5435 🟡 MEDIUM libc-bin 2.41-12+deb13u2 N/A
CVE-2026-5450 🟡 MEDIUM libc-bin 2.41-12+deb13u2 N/A
CVE-2026-5928 🟡 MEDIUM libc-bin 2.41-12+deb13u2 N/A
CVE-2026-4046 🟡 MEDIUM libc6 2.41-12+deb13u2 N/A
CVE-2026-4437 🟡 MEDIUM libc6 2.41-12+deb13u2 N/A
CVE-2026-4438 🟡 MEDIUM libc6 2.41-12+deb13u2 N/A
CVE-2026-5435 🟡 MEDIUM libc6 2.41-12+deb13u2 N/A
CVE-2026-5450 🟡 MEDIUM libc6 2.41-12+deb13u2 N/A
CVE-2026-5928 🟡 MEDIUM libc6 2.41-12+deb13u2 N/A
CVE-2026-27456 🟡 MEDIUM liblastlog2-2 2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM liblastlog2-2 2.41-5 N/A
CVE-2026-34743 🟡 MEDIUM liblzma5 5.8.1-1 N/A
CVE-2026-27456 🟡 MEDIUM libmount1 2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM libmount1 2.41-5 N/A
CVE-2026-27456 🟡 MEDIUM libsmartcols1 2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM libsmartcols1 2.41-5 N/A
CVE-2026-40225 🟡 MEDIUM libsystemd0 257.9-1~deb13u1 N/A
CVE-2026-40226 🟡 MEDIUM libsystemd0 257.9-1~deb13u1 N/A
CVE-2026-4105 🟡 MEDIUM libsystemd0 257.9-1~deb13u1 N/A
CVE-2026-40225 🟡 MEDIUM libudev1 257.9-1~deb13u1 N/A
CVE-2026-40226 🟡 MEDIUM libudev1 257.9-1~deb13u1 N/A
CVE-2026-4105 🟡 MEDIUM libudev1 257.9-1~deb13u1 N/A
CVE-2026-27456 🟡 MEDIUM libuuid1 2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM libuuid1 2.41-5 N/A
CVE-2026-27456 🟡 MEDIUM login 1:4.16.0-2+really2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM login 1:4.16.0-2+really2.41-5 N/A
CVE-2026-27456 🟡 MEDIUM mount 2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM mount 2.41-5 N/A
CVE-2026-5958 🟡 MEDIUM sed 4.9-2 N/A
CVE-2026-5704 🟡 MEDIUM tar 1.35+dfsg-3.1 N/A
CVE-2026-27456 🟡 MEDIUM util-linux 2.41-5 N/A
CVE-2026-3184 🟡 MEDIUM util-linux 2.41-5 N/A
CVE-2026-27171 🟡 MEDIUM zlib1g 1:1.3.dfsg+really1.3.1-1+b1 N/A
CVE-2026-3219 🟡 MEDIUM pip 26.0.1 N/A
CVE-2026-6357 🟡 MEDIUM pip 26.0.1 26.1
CVE-2011-3374 🔵 LOW apt 3.0.3 N/A

...and 64 more

⚓ Grype Scanner (0 findings, 0 unique)

✅ No vulnerabilities detected by Grype

⚠️ scanner-supply-chain - 9 vulnerabilities (9 unique)

Image: ghcr.io/huntridge-labs/argus/scanner-supply-chain:19236951317d0f7b30fd807408558548f0b20cbb

Combined (Deduplicated)

🚨 Critical ⚠️ High 🟡 Medium 🔵 Low Total Unique
0 4 5 0 9 9
🔷 Trivy Scanner (9 findings, 9 unique)
CVE Severity Package Version Fixed
CVE-2026-32280 ⚠️ HIGH stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-32281 ⚠️ HIGH stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-32283 ⚠️ HIGH stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-33810 ⚠️ HIGH stdlib v1.26.1 1.26.2
CVE-2026-3219 🟡 MEDIUM pip 26.0.1 N/A
CVE-2026-6357 🟡 MEDIUM pip 26.0.1 26.1
CVE-2026-32282 🟡 MEDIUM stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-32288 🟡 MEDIUM stdlib v1.26.1 1.25.9, 1.26.2
CVE-2026-32289 🟡 MEDIUM stdlib v1.26.1 1.25.9, 1.26.2
⚓ Grype Scanner (0 findings, 0 unique)

✅ No vulnerabilities detected by Grype


Generated by Argus

The validate-success summary listed scanners, formats, and backend but
ignored the top-level containers block entirely. With containers
silently absent from the summary the user had no signal that argus
validate had inspected it — a typo at the block name (e.g.
``containerz:``) would still show up as a top-level-key warning, but a
correctly-named block with valid contents looked identical to no block
at all.

Add a Containers line that shows:
  Containers: 4 image(s)
    - ghcr.io/myorg/scanner-bandit:dev
    - ghcr.io/myorg/scanner-opengrep:dev
    ...
  Containers: discover from docker/, .
  Containers: 2 image(s) + discover from docker/

The line is only printed when the block is structurally a mapping; if
no containers block exists, the validator stays silent (matching the
optional nature of the block). Three new regression tests in
TestCmdValidate cover the present, absent, and discover variants.
@eFAILution eFAILution merged commit 0bf1a26 into feat/argus-portability May 6, 2026
51 checks passed
@eFAILution eFAILution deleted the fix/argus-validate-containers-and-followups branch May 6, 2026 02:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant